package com.fulihui.usercore.biz.conv;

import com.alibaba.fastjson.JSON;
import com.fulihui.usercore.dal.dataobj.UserDOWithBLOBs;
import com.fulihui.usercore.dto.UserDTO;
import com.fulihui.usercore.enums.BooleanValueEnum;
import com.fulihui.usercore.enums.UserUsedProducts;
import com.google.common.collect.Maps;
import org.near.toolkit.common.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.fulihui.usercore.common.util.DataSafe.*;

/**
 * 用户信息DO、DTO转换工具类，使用 Spring 管理此类的单例特性
 * @author Willard.Hu on 2016/5/19.
 */
@Component
public class UserConv {
    /**
     * 数据加密的 AES KEY
     */
    @Value("${data.safe.aeskey}")
    private String dataSafeAesKey;

    public String getDataSafeAesKey() {
        return dataSafeAesKey;
    }

    /**
     * Spring BeanUtils.copyProperties对象参数拷贝过滤的字段
     */
    private static final String[] ignore = {"registerType", "mobileVerified", "idcardVerified",
            "emailVerified", "gender", "state", "extInfo", "usedProducts", "lastLogin",
            "gmtCreate", "gmtModified"};

    /**
     * 用户信息 DTO 转换 DO 对象
     * @param dto {@link UserDTO}
     * @param oldExtInfo 数据库中的扩展字段，考虑到上层使用时，扩展字段会传不全，扩展字段不直接覆盖，
     * 遍历Map将新的值覆盖旧的值，再写入数据库
     * @return 转换后的 {@link UserDOWithBLOBs} 对象
     */
    public UserDOWithBLOBs toDO(UserDTO dto, Map<String, Object> oldExtInfo) {
        if (dto == null) {
            return null;
        }
        UserDOWithBLOBs userDO = new UserDOWithBLOBs();
        BeanUtils.copyProperties(dto, userDO, ignore);

        // 敏感数据 AES 加密处理
        if (StringUtil.isNotBlank(userDO.getMobileNo())) {
            userDO.setMobileNo(aesEncrypt(userDO.getMobileNo(), dataSafeAesKey));
        }
        if (StringUtil.isNotBlank(userDO.getIdcard())) {
            userDO.setIdcard(aesEncrypt(userDO.getIdcard(), dataSafeAesKey));
        }
        if (StringUtil.isNotBlank(userDO.getEmail())) {
            userDO.setEmail(aesEncrypt(userDO.getEmail(), dataSafeAesKey));
        }
        if (StringUtil.isNotBlank(userDO.getTelephone())) {
            userDO.setTelephone(aesEncrypt(userDO.getTelephone(), dataSafeAesKey));
        }
        if (StringUtil.isNotBlank(userDO.getNickname())) {
            Optional<String> optional = baseEncode(userDO.getNickname());
            optional.ifPresent(userDO::setNickname);
        }

        if (dto.getRegisterType() != null) {
            userDO.setRegisterType(dto.getRegisterType());
        }
        if (dto.getMobileVerified() != null) {
            userDO.setMobileVerified(BooleanValueEnum.byBoolean(dto.getMobileVerified()).getCode());
        }
        if (dto.getIdcardVerified() != null) {
            userDO.setIdcardVerified(BooleanValueEnum.byBoolean(dto.getIdcardVerified()).getCode());
        }
        if (dto.getEmailVerified() != null) {
            userDO.setEmailVerified(BooleanValueEnum.byBoolean(dto.getEmailVerified()).getCode());
        }
        if (dto.getGender() != null) {
            userDO.setGender(dto.getGender());
        }
        if (dto.getState() != null) {
            userDO.setState(dto.getState());
        }
        if (!CollectionUtils.isEmpty(dto.getTagIds())) {
            userDO.setTags(dto.getTagIds().stream().collect(Collectors.joining(",")));
        } else {
            userDO.setTags("");
        }
        if (dto.getExtInfo() != null) { // 传入的扩展信息不为空
            if (oldExtInfo != null) {
                // 遍历扩展信息做增量更新
                dto.getExtInfo().entrySet().stream().filter(entry -> entry.getValue() != null)
                        .forEach(entry -> oldExtInfo.put(entry.getKey(), entry.getValue()));
                userDO.setExtInfo(JSON.toJSONString(oldExtInfo));
            } else {
                // 历史没有扩展信息用新的扩展信息
                userDO.setExtInfo(JSON.toJSONString(dto.getExtInfo()));
            }
        }
        if (!CollectionUtils.isEmpty(dto.getUsedProducts())) {
            List<UserUsedProducts> usedProducts = dto.getUsedProducts().stream()
                    .map(UserUsedProducts::findByName)
                    .collect(Collectors.toList());
            userDO.setUsedProducts(UserUsedProducts.unionOf(usedProducts));
        }
        userDO.setLastLogin(dto.lastLogin());
        return userDO;
    }

    /**
     * 用户信息 DO 转 DTO 对象
     * @param userDO {@link UserDOWithBLOBs}
     * @return 转换后的 {@link UserDTO} 对象
     */
    public UserDTO toDTO(UserDOWithBLOBs userDO) {
        if (userDO == null) {
            return null;
        }
        UserDTO dto = new UserDTO();
        BeanUtils.copyProperties(userDO, dto, ignore);

        // 敏感数据 AES 解密处理
        if (StringUtil.isNotBlank(dto.getMobileNo())) {
            dto.setMobileNo(autoDecrypt(dto.getMobileNo()));
        }
        if (StringUtil.isNotBlank(dto.getIdcard())) {
            dto.setIdcard(autoDecrypt(dto.getIdcard()));
        }
        if (StringUtil.isNotBlank(dto.getEmail())) {
            dto.setEmail(autoDecrypt(dto.getEmail()));
        }
        if (StringUtil.isNotBlank(dto.getTelephone())) {
            dto.setTelephone(autoDecrypt(dto.getTelephone()));
        }
        if (StringUtil.isNotBlank(dto.getNickname())) {
            dto.setNickname(autoDecrypt(dto.getNickname()));
        }

        dto.setRegisterType(userDO.getRegisterType());
        dto.setMobileVerified(BooleanValueEnum.byCode(userDO.getMobileVerified()).isTrue());
        dto.setIdcardVerified(BooleanValueEnum.byCode(userDO.getIdcardVerified()).isTrue());
        dto.setEmailVerified(BooleanValueEnum.byCode(userDO.getEmailVerified()).isTrue());
        dto.setGender(userDO.getGender());
        dto.setState(userDO.getState());
        if (StringUtil.isNotBlank(userDO.getTags())) {
            dto.setTagIds(Arrays.asList(userDO.getTags().split(",")));
        }
        if (StringUtil.isNotBlank(userDO.getExtInfo())) {
            dto.setExtInfo(JSON.parseObject(userDO.getExtInfo()));
        }
        if (userDO.getUsedProducts() != null && userDO.getUsedProducts() > 0) {
            List<String> usedProducts = UserUsedProducts.toList(userDO.getUsedProducts()).stream()
                    .map(UserUsedProducts::name)
                    .collect(Collectors.toList());
            dto.setUsedProducts(usedProducts);
        }
        dto.lastLogin(userDO.getLastLogin());
        dto.gmtCreate(userDO.getGmtCreate());
        dto.gmtModified(userDO.getGmtModified());
        return dto;
    }

    /**
     * 用户信息 DO 转 DTO 对象，批量处理
     * @param doList 用户信息 {@link UserDOWithBLOBs} 集合
     * @return 转换后的用户信息 {@link UserDTO} 集合
     */
    public List<UserDTO> toList(List<UserDOWithBLOBs> doList) {
        if (CollectionUtils.isEmpty(doList)) {
            return Collections.emptyList();
        }
        return doList.stream().map(this::toDTO).collect(Collectors.toList());
    }

    /**
     * 用户信息 DO 转 DTO 对象，批量处理
     * @param doList 用户信息 {@link UserDOWithBLOBs} 集合
     * @return 转换后的用户信息 {@link UserDTO} 字典
     */
    public Map<String, UserDTO> toMap(List<UserDOWithBLOBs> doList) {
        if (CollectionUtils.isEmpty(doList)) {
            return Collections.emptyMap();
        }
        Map<String, UserDTO> map = Maps.newHashMap();
        for (UserDOWithBLOBs user : doList) {
            map.put(user.getUserId(), toDTO(user));
        }
        return map;
    }

    public static void main(String[] args) {
        String s = autoDecrypt("AES-ABDPKb8tsjEfmwLdwr5yClBX3BNjIeNurztRe5JvEk4yMQ==");
        System.out.println(s);
    }
}
